package ophiux.wechatpay.sdk.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import ophiux.wechatpay.sdk.common.utils.StringUtil;

public class SignUtils {
	/**
	 * 签名算法
	 * @param paramMap  参数集合
	 * @param key  密钥
	 * @return
	 * @throws Exception
	 */
	public static String getSign(Map<String, String> paramMap, String key)
			throws Exception {
		String sign = "";
//		// 拼接排序
//		List<Map.Entry<String, String>> mapList = new ArrayList<Map.Entry<String, String>>(
//				paramMap.entrySet());
//		Collections.sort(mapList, new Comparator<Map.Entry<String, String>>() {
//			@Override
//			public int compare(Entry<String, String> entry1,
//					Entry<String, String> entry2) {
//				// 根据第一个字母排序
//				String first = entry1.getValue().substring(0, 1);
//				String second = entry2.getValue().substring(0, 1);
//				return first.compareTo(second);
//			}
//		});
		SortedMap<String, String> sortMap = new TreeMap(paramMap);
		// 拼接sign
		for (Entry<String, String> entry : sortMap.entrySet()) {
			if (StringUtil.isEmpty(entry.getValue())) {
				continue;
			}
			if ("key".equals(entry.getKey())) {
				continue;
			}
			sign = sign + entry.getKey() + "=" + entry.getValue() + "&";
		}
		// TODO 密钥
		sign = sign + "key=" + key;
		System.out.println("签名参数:"+sign);
		// MD5
		sign = MD5Utils.md5Encode(sign);
		System.out.println("签名:"+sign);
		return sign;
	}

	/**
	 * 构造签名
	 * 
	 * @param params
	 * @param encode
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String createSign(Map<String, String> params, boolean encode)
			throws UnsupportedEncodingException {
		Set<String> keysSet = params.keySet();
		Object[] keys = keysSet.toArray();
		Arrays.sort(keys);
		StringBuffer temp = new StringBuffer();
		boolean first = true;
		for (Object key : keys) {
			if (first) {
				first = false;
			} else {
				temp.append("&");
			}
			temp.append(key).append("=");
			Object value = params.get(key);
			String valueString = "";
			if (null != value) {
				valueString = value.toString();
			}
			if (encode) {
				temp.append(URLEncoder.encode(valueString, "UTF-8"));
			} else {
				temp.append(valueString);
			}
		}
		return temp.toString();
	}

	/**
	 * 支付回调校验签名
	 * 
	 * @param timestamp
	 * @param noncestr
	 * @param openid
	 * @param issubscribe
	 * @param appsignature
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static boolean verifySign(long timestamp, String noncestr,
			String openid, int issubscribe, String appsignature)
			throws UnsupportedEncodingException {
		Map<String, String> paras = new HashMap<String, String>();
		paras.put("appid", "");
		paras.put("appkey", "");
		paras.put("timestamp", String.valueOf(timestamp));
		paras.put("noncestr", noncestr);
		paras.put("openid", openid);
		paras.put("issubscribe", String.valueOf(issubscribe));
		// appid、appkey、productid、timestamp、noncestr、openid、issubscribe
		String string1 = createSign(paras, false);
		String paySign = DigestUtils.shaHex(string1);
		return paySign.equalsIgnoreCase(appsignature);
	}

	/**
	 * 支付回调校验签名
	 * 
	 * @param timestamp
	 * @param noncestr
	 * @param openid
	 * @param issubscribe
	 * @param appsignature
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static boolean verifySign(long timestamp, String noncestr,
			String openid, String appsignature)
			throws UnsupportedEncodingException {
		Map<String, String> paras = new HashMap<String, String>();
		paras.put("appid", "");
		paras.put("appkey", "");
		paras.put("timestamp", String.valueOf(timestamp));
		paras.put("noncestr", noncestr);
		paras.put("openid", openid);
		// appid、appkey、productid、timestamp、noncestr、openid、issubscribe
		String string1 = createSign(paras, false);
		String paySign = DigestUtils.shaHex(string1);
		return paySign.equalsIgnoreCase(appsignature);
	}
	
	
}
